import 'package:built_collection/built_collection.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:mobile_app.core/core/domain/entities/learning_content/collection_list_item/collection_list_item.dart';
import 'package:mobile_app.core/core/domain/entities/learning_content/lexical_item/lexical_item.dart';
import 'package:mobile_app.core/core/domain/entities/premium_access_status.dart';
import 'package:mobile_app.core/core/domain/repositories/learning_content_repository/repository.dart';
import 'package:mobile_app.home.collections/collection_selection_page/domain/helpers/get_collection_progress_persent/helper.dart';
import 'package:mobile_app.home.collections/collection_selection_page/domain/helpers/is_collection_list_item_creation_permitted/helper.dart';
import 'package:mobile_app.home.collections.core/core/domain/helpers/create_custom_collection/helper.dart';
import 'package:mobile_app.home.collections.core/core/domain/helpers/validate_custom_collection_title/helper.dart';
import 'package:mobile_app.home.core/core/domain/helpers/get_permitted_collection_list_item_ids/helper.dart';
import 'package:mobile_app.home.core/core/domain/helpers/is_collection_selection_effective/helper.dart';

part 'failures.dart';

part 'result.dart';

abstract class CompleteCollectionCreation {
  Either<CollectionCreationCompletionFailure, CollectionCreationCompletionResult> call({
    required String collectionTitleInput,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
    required BuiltList<CollectionListItem> collectionListItems,
    required PremiumAccessStatus premiumAccessStatus,
    required BuiltMap<String, int> collectionProgressPercentMap,
    required BuiltSet<String> effectivelySelectedCollectionIds,
  });
}

class CompleteCollectionCreationImpl implements CompleteCollectionCreation {
  const CompleteCollectionCreationImpl({
    required CreateCustomCollection createCustomCollection,
    required GetCollectionProgressPercent getCollectionProgressPercent,
    required GetPermittedCollectionListItemIds getPermittedCollectionListItemIds,
    required IsCollectionListItemCreationPermitted isCollectionListItemCreationPermitted,
    required IsCollectionSelectionEffective isCollectionSelectionEffective,
    required ValidateCustomCollectionTitle validateCustomCollectionTitle,
    required LearningContentRepository learningContentRepository,
  })  : _createCustomCollection = createCustomCollection,
        _getCollectionProgressPercent = getCollectionProgressPercent,
        _getPermittedCollectionListItemIds = getPermittedCollectionListItemIds,
        _isCollectionListItemCreationPermitted = isCollectionListItemCreationPermitted,
        _isCollectionSelectionEffective = isCollectionSelectionEffective,
        _validateCustomCollectionTitle = validateCustomCollectionTitle,
        _learningContentRepository = learningContentRepository;

  final CreateCustomCollection _createCustomCollection;
  final GetCollectionProgressPercent _getCollectionProgressPercent;
  final GetPermittedCollectionListItemIds _getPermittedCollectionListItemIds;
  final IsCollectionListItemCreationPermitted _isCollectionListItemCreationPermitted;
  final IsCollectionSelectionEffective _isCollectionSelectionEffective;
  final ValidateCustomCollectionTitle _validateCustomCollectionTitle;

  final LearningContentRepository _learningContentRepository;

  @override
  Either<CollectionCreationCompletionFailure, CollectionCreationCompletionResult> call({
    required String collectionTitleInput,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
    required BuiltList<CollectionListItem> collectionListItems,
    required PremiumAccessStatus premiumAccessStatus,
    required BuiltMap<String, int> collectionProgressPercentMap,
    required BuiltSet<String> effectivelySelectedCollectionIds,
  }) {
    final trimmedCollectionTitleInput = collectionTitleInput.trim();

    final validationError = _validateCustomCollectionTitle(
      customCollectionTitle: trimmedCollectionTitleInput,
    );

    if (validationError != null) {
      final failure = InvalidCollectionTitleCollectionCreationCompletionFailure(
        validationError: validationError,
      );

      return left(failure);
    }

    final collection = _createCustomCollection(
      collectionTitle: trimmedCollectionTitleInput,
    );

    var index = 0;

    if (collectionListItems.isNotEmpty) {
      while (collectionListItems[index] is CustomCollectionListItem) {
        index++;
      }
    }

    // unexpected crash in release

    // final updatedCollectionListItems = collectionListItems.rebuild((collectionListItems) {
    //   collectionListItems.insert(index, collection);
    // });

    // final updatedCollectionListItems = collectionListItems.rebuild((collectionListItems) {
    //   collectionListItems.insert(index, collectionFolder);
    // });

    final updatedCollectionListItemList = <CollectionListItem>[
      ...collectionListItems,
    ];

    updatedCollectionListItemList.insert(index, collection);

    final updatedCollectionListItems = updatedCollectionListItemList.build();

    final permittedCollectionListItemIds = _getPermittedCollectionListItemIds(
      collectionListItems: updatedCollectionListItems,
      premiumAccessStatus: premiumAccessStatus,
    );

    final collectionListItemCreationPermitted = _isCollectionListItemCreationPermitted(
      premiumAccessStatus: premiumAccessStatus,
    );

    final collectionProgressPercent = _getCollectionProgressPercent(
      collection: collection,
      lexicalItemMap: lexicalItemMap,
    );

    final updatedCollectionProgressPercentMap =
        collectionProgressPercentMap.rebuild((collectionProgressPercentMap) {
      collectionProgressPercentMap[collection.id] = collectionProgressPercent;
    });

    final collectionPermitted = permittedCollectionListItemIds.contains(collection.id);

    final collectionSelectionEffective = _isCollectionSelectionEffective(
      collection: collection,
      collectionPermitted: collectionPermitted,
    );

    final updatedEffectivelySelectedCollectionIds =
        effectivelySelectedCollectionIds.rebuild((effectivelySelectedCollectionIds) {
      if (collectionSelectionEffective) {
        effectivelySelectedCollectionIds.add(collection.id);
      }
    });

    final result = CollectionCreationCompletionResult(
      collectionListItems: updatedCollectionListItems,
      collectionProgressPercentMap: updatedCollectionProgressPercentMap,
      effectivelySelectedCollectionIds: updatedEffectivelySelectedCollectionIds,
      permittedCollectionListItemIds: permittedCollectionListItemIds,
      collectionListItemCreationPermitted: collectionListItemCreationPermitted,
    );

    _learningContentRepository.saveCollectionListItems(
      collectionListItems: updatedCollectionListItems,
    );

    return right(result);
  }
}
